﻿// Open Source: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Project: YoProgramo.NET (http://code.google.com/p/yoprogramo/)
// Autor: Fabian Figueredo (info@fabianfigueredo.com.ar)
// Blog: blog.yoprogramo.net

using System;
using System.Collections.Generic;
using System.Linq;
using NHibernate.Validator.Engine;
using YoProgramo.Domain.BusinessLogic.Extensions;
using YoProgramo.Domain.Core.Entities;
using YoProgramo.Domain.Core.Exceptions;
using YoProgramo.Domain.Core.Interfaces;
using YoProgramo.Infrastructure.Tools.NHValidator;

namespace YoProgramo.Domain.BusinessLogic.Service
{
    public class StoryService : IStoryService {

        private IStoryRepository _StoryRepository;
        private IUserRepository _UserRepository;

        public StoryService(IStoryRepository storyreposotory, IUserRepository UserRepository)
        {
            _StoryRepository = storyreposotory;
            _UserRepository = UserRepository;
        }

        #region IStoryService Members

        public InvalidValue[] Create(IStory obj) {
            try
            {
                InvalidValue[] validatorErrors = new NHValidatorWrapper<Story>().Validate((Story)obj);

                if (validatorErrors.Count() < 1)
                    _StoryRepository.SaveOrUpdate(obj);

                return validatorErrors;
            }
            catch (Exception ex)
            {
                throw new YPException("Error: Cannot create story", ex); 
            }

        }

        public bool Update(IStory obj) {
            try
            {
                InvalidValue[] validatorErrors = new NHValidatorWrapper<Story>().Validate((Story)obj);

                if (validatorErrors.Count() < 1)
                    _StoryRepository.SaveOrUpdate(obj);

                return true;
            }
            catch
            {
                return false;
            }
        }

        public void Delete(IStory obj) {
            _StoryRepository.Delete(obj);
        }


        public IList<IStory> GetAll() {
            return _StoryRepository.GetAll();
        }


        public IList<IStory> GetAllNotSpam() {
            return (from s in GetAll()
                    where !s.HasSpam() && !s.IsLockedOut
                    orderby s.PostedAt descending
                    select s).ToList();
        }


        public IList<IStory> GetByTag(ITag tag) {
            return (from s in GetAllNotSpam()
                    where s.Tags.Contains((Tag)tag)
                    orderby s.PostedAt descending
                    select s).ToList();
        }


        public IList<IStory> GetByCategory(ICategory category) {
            return (from s in GetAllNotSpam()
                    where s.Category.Id == category.Id
                    orderby s.PostedAt descending
                    select s).ToList();
        }


        public IStory GetBySlug(string slug) {
            return GetAll().FirstOrDefault(w => w.Slug == slug);
        }

        public IList<IUser> GetUsersFavForStory(IStory story) {
            return  (from s in _UserRepository.GetAll()
                     where s.FavoritesStories.Contains(story) 
                     select s).ToList();            
        }


        public IList<IStory> GetByUser(IUser user) {
            return (from s in GetAllNotSpam()
                    where s.ByUser == user
                    orderby s.PostedAt descending
                    select s).ToList();
        }


        public IList<IStory> GetAllWOutAnswer() {
            return (from s in GetAllNotSpam()
                    where s.Comments.Count == 0
                    orderby s.PostedAt descending
                    select s).ToList();
        }

        public IList<IStory> GetStoriesForHome(int? top) {
            return (from s in GetAllNotSpam()
                    where !s.ByUser.IsLockedOut
                    orderby s.GetWeightFactor() descending, s.PostedAt descending
                    select s).Take(top ?? 100).ToList();
        }

        #endregion
    }
}